import SwiftUI

/// 磁吸方向
public enum DragViewMagnetDirection {
    case top, right, bottom, left
}


public struct DragView<Content: View>: View {
 
    public init(position: Binding<CGPoint>, isAllowedMagnetDirections: Set<DragViewMagnetDirection> = [], @ViewBuilder content: @escaping () -> Content) {
        
        self._position = position
        self.isAllowedMagnetDirections = isAllowedMagnetDirections
        self.content = content
    }
    
    @Binding private var position: CGPoint
    /// 允许磁吸的方向
    private var isAllowedMagnetDirections: Set<DragViewMagnetDirection> = [.top, .right, .bottom, .left]
    
    @ViewBuilder private var content: () -> Content
    
    @State private var contentSize: CGSize?
    
    public var body: some View {
        GeometryReader(content: { geometry in
            content()
                .background(
                    GeometryReader(content: { reader in
                       
                        Color.blue
                            .onAppear(perform: {
                                contentSize = reader.frame(in: .local).size
                            })
                    })
                )
                .position(position)
                .gesture(
                    DragGesture()
                        .onChanged({ value in
                            position = value.location
                        })
                        .onEnded({ value in
                            
                            withAnimation {
                                magnetEndPosition(geometry: geometry, center: value.location)
                            }
                        })
                )
                .onAppear(perform: {
                   
                    magnetEndPosition(geometry: geometry, center: position)
                    
                })
        })
        .clipped()
    }
    
    private func magnetEndPosition(geometry: GeometryProxy, center: CGPoint) {
        
        
        let superFrame = geometry.frame(in: .global)
        
        print(superFrame, center)
        
        if let contentSize {
            
            let centerX = center.x
            let centerY = center.y
            
            
            var x: CGFloat = centerX - contentSize.width / 2.0
            var y: CGFloat = centerY - contentSize.height / 2.0
            
            var isMagnetV: Bool = false
            
            if isAllowedMagnetDirections.contains(.top) {
                
                if !isAllowedMagnetDirections.contains(.bottom) && !isAllowedMagnetDirections.contains(.left) && !isAllowedMagnetDirections.contains(.right) {
                    y = 0
                    isMagnetV = true
                }else {
                    if centerY <= contentSize.height {
                        y = 0
                        isMagnetV = true
                    }
                }
            }
            
            if isAllowedMagnetDirections.contains(.bottom) {
                if !isAllowedMagnetDirections.contains(.top) && !isAllowedMagnetDirections.contains(.left) && !isAllowedMagnetDirections.contains(.right) {
                    
                    y = superFrame.height - contentSize.height
                    isMagnetV = true
                }else {
                    
                    if centerY >= superFrame.height - contentSize.height {
                        y = superFrame.height - contentSize.height
                        isMagnetV = true
                    }
                }
            }
            
            if isAllowedMagnetDirections.contains(.left) {
                if !isAllowedMagnetDirections.contains(.right) {
                    if !isMagnetV {
                        x = 0
                    }
                }else {
                    
                    if centerX <= superFrame.width / 2.0 {
                        if !isMagnetV {
                            x = 0
                        }
                    }
                }
                
            }
            
            if isAllowedMagnetDirections.contains(.right) {
                
                if !isAllowedMagnetDirections.contains(.left) {
                    if !isMagnetV {
                        x = superFrame.width - contentSize.width
                    }
                }else {
                    
                    if centerX > superFrame.width / 2.0 {
                        if !isMagnetV {
                            x = superFrame.width - contentSize.width
                        }
                    }
                }
            }

            
            y = min(max(0, y), superFrame.height - contentSize.height)
            x = min(max(0, x), superFrame.width - contentSize.width)
            
            
            position = CGPoint(x: x + contentSize.width / 2.0, y: y + contentSize.height / 2.0)
        }
    }
}

private struct DragViewTest: View {
    @State var position: CGPoint = .zero
    var body: some View {
        
        DragView(position: $position, isAllowedMagnetDirections: [.top, .left, .bottom, .right]) {
            
            Color.red
                .frame(width: 80, height: 80)
        }
        .frame(width: 200, height: 200)
    }
}


#Preview {
    
    DragViewTest()
}
